package com.bimrun.gis.util;

import org.apache.http.HttpEntity;
import org.apache.http.client.methods.*;
import org.apache.http.config.SocketConfig;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URI;

@Component
public class HttpClientUtil {
    //todo 连接池是否能提升并发的请求性能
    CloseableHttpClient client;

    public HttpClientUtil() {
        PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
        connManager.setMaxTotal(200);
        SocketConfig socketConfig = SocketConfig.custom()
                .setTcpNoDelay(true)     //是否立即发送数据，设置为true会关闭Socket缓冲，默认为false
                .setSoReuseAddress(true) //是否可以在一个进程关闭Socket后，即使它还没有释放端口，其它进程还可以立即重用端口
                .setSoLinger(60)         //关闭Socket时，要么发送完所有数据，要么等待60s后，就关闭连接，此时socket.close()是阻塞的
                .setSoKeepAlive(true)    //开启监视TCP连接是否有效
                .build();
        connManager.setDefaultSocketConfig(socketConfig);

        this.client  = HttpClients.custom()
                .setConnectionManager(connManager)             //连接管理器
                .build();
    }

    public RequestBuilder buildRequest() {
        return new RequestBuilder();
    }

    public class RequestBuilder {
        private HttpRequestBase request;
        private HttpEntity response;

        public RequestBuilder() {
        }

        public RequestBuilder buildPost(URI url) throws IOException {
            request = new HttpPost(url);
            return this;
        }

        public RequestBuilder buildGet(URI url) {
            request = new HttpGet(url);
            return this;
        }

        public RequestBuilder addHeader(String name, String value) {
            request.addHeader(name, value);
            return this;
        }

        public RequestBuilder setEntity(HttpEntity entity) {
//            RequestConfig.Builder custom = RequestConfig.custom();
//            request.setConfig(defaultConfig);
            HttpPost post = (HttpPost) request;
            post.setEntity(entity);
            return this;
        }

        public RequestBuilder getResponse() throws IOException {
            if (request == null) {
                throw new RuntimeException("build request first");
            }
            CloseableHttpResponse execute = client.execute(request);
            response = execute.getEntity();
            return this;
        }

        public String getString() throws IOException {
            if (response == null) {
                throw new RuntimeException("get response first");
            }
            String result = EntityUtils.toString(response);
            close();
            return result;
        }

        public byte[] getBytes() throws IOException {
            if (response == null) {
                throw new RuntimeException("get response first");
            }
            byte[] bytes = EntityUtils.toByteArray(response);
            close();
            return bytes;
        }

        public File writeToFile(String fileName) throws IOException {
            File file = new File(fileName);
            File parentFile = file.getParentFile();

            if (!parentFile.exists()) {
                parentFile.mkdirs();
            }

            if (!file.exists()) {
                FileOutputStream fos = new FileOutputStream(fileName);
                response.writeTo(fos);
                fos.close();
                fos.flush();
            }
            close();
            return file;
        }

        private void close() throws IOException {
            response.getContent().close();
        }
    }

}
